home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / port / linux / dynloader.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-18  |  5.1 KB  |  243 lines

  1. /*
  2.      $Header: /private/postgres/src/port/linux/RCS/dynloader.c,v 1.14 1992/01/12 23:29:23 mao Exp $
  3. */
  4.  
  5. #include <pwd.h>
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <sys/types.h>
  9. #include <sys/param.h>
  10. #include <sys/stat.h>
  11. #include <sys/file.h>
  12.  
  13. extern char pg_pathname[];
  14.  
  15. #include <a.out.h>
  16.  
  17. #include "tmp/c.h"
  18. #include "utils/fmgr.h"
  19.  
  20. /*
  21.  * Allow extra space for "overruns" caused by the link.
  22.  */
  23.  
  24. #define FUDGE 10000
  25.  
  26. static char *temp_file_name = NULL;
  27. static char *path = "/usr/tmp/postgres";
  28.  
  29. DynamicFunctionList *
  30. dynamic_file_load(err, filename, address, size)
  31.  
  32. char **err, *filename, **address;
  33. long *size;
  34.  
  35. {
  36.     extern char *valloc();
  37.  
  38.     int nread;
  39.     struct exec ld_header, header;
  40.     unsigned long image_size, true_image_size;
  41.     char *load_address = NULL;
  42.     FILE *temp_file = NULL;
  43.     DynamicFunctionList *retval = NULL;
  44.     DynamicFunctionList *load_symbols(int, struct exec *, int);
  45.     int fd;
  46.     char foo[10];
  47.  
  48.     fd = open(filename, O_RDONLY);
  49.  
  50.     if (fd == -1)
  51.     {
  52.         *err = "error opening file";
  53.         goto finish_up;
  54.     }
  55.  
  56.     read(fd, &ld_header, sizeof(struct exec));
  57.  
  58.     image_size = ld_header.a_text + ld_header.a_data + ld_header.a_bss + FUDGE;
  59.  
  60.     if (!(load_address = valloc(image_size)))
  61.     {
  62.         *err = "unable to allocate memory";
  63.         goto finish_up;
  64.     }
  65.  
  66.     if (temp_file_name == NULL)
  67.     {
  68.         sprintf(foo, "%d", getpid());
  69.         temp_file_name = (char *)malloc(strlen(path) + strlen(foo) + 2);
  70.         strcpy(temp_file_name, path);
  71.         strcat(temp_file_name, foo);
  72.     }
  73.  
  74.     if(execld(load_address, temp_file_name, filename))
  75.     {
  76.         *err = "ld failed!";
  77.         goto finish_up;
  78.     }
  79.  
  80.     if(!(temp_file = fopen(temp_file_name,"r")))
  81.     {
  82.         *err = "unable to open tmp file";
  83.         goto finish_up;
  84.     }
  85.     nread = fread(&header, sizeof(header), 1, temp_file);
  86.     true_image_size = header.a_text + header.a_data + header.a_bss;
  87.  
  88.     if (true_image_size > image_size)
  89.     {
  90.         fclose(temp_file);
  91.         free(load_address);
  92.         load_address = valloc(true_image_size);
  93.  
  94.         if (execld(load_address, temp_file_name, filename))
  95.         {
  96.             *err = "ld failed!";
  97.             goto finish_up;
  98.         }
  99.         temp_file = fopen(temp_file_name,"r");
  100.         nread = fread(&header, sizeof(header), 1, temp_file);
  101.     }
  102.  
  103.     fseek(temp_file, N_TXTOFF(header), 0);
  104.     nread = fread(load_address, true_image_size,1,temp_file);
  105.  
  106.     retval = load_symbols(fd, &ld_header, (int) load_address);
  107.  
  108.     fclose(temp_file);
  109.     unlink(temp_file_name);
  110.     *address = load_address;
  111.     *size = image_size;
  112.  
  113.     temp_file = NULL;
  114.     load_address = NULL;
  115.  
  116. finish_up:
  117.     if (temp_file != NULL) fclose(temp_file);
  118.     if (load_address != NULL) free(load_address);
  119.     return retval;
  120. }
  121.  
  122. DynamicFunctionList *
  123. load_symbols(int fd, struct exec *hdr, int entry_addr)
  124. {
  125.     char *strings, *symb_table, *p, *q;
  126.     int symtab_offset, string_offset, string_size, nsyms, i;
  127.     struct nlist *table_entry;
  128.     int entering = 1;
  129.     DynamicFunctionList *head, *scanner;
  130.  
  131.     symtab_offset = N_SYMOFF(*hdr);
  132.     string_offset = N_STROFF(*hdr);
  133.  
  134.     lseek(fd, string_offset, 0);
  135.     read(fd, &string_size, sizeof(string_size));
  136.     strings = (char *) malloc(string_size - 4);
  137.     read(fd, strings, string_size - 4);
  138.     nsyms = hdr->a_syms / sizeof(struct nlist);
  139.     lseek(fd, symtab_offset, 0);
  140.     symb_table = (char *) malloc(hdr->a_syms);
  141.     read(fd, symb_table, hdr->a_syms);
  142.  
  143.     p = symb_table;
  144.     for (i = 0; i < nsyms; i++)
  145.     {
  146.         table_entry = (struct nlist *) p;
  147.         p += sizeof(struct nlist);
  148.  
  149.         if ((table_entry->n_type & N_EXT) &&
  150.             (table_entry->n_type & N_TYPE) == N_TEXT)
  151.         {
  152.             if (entering)
  153.             {
  154.                 head = (DynamicFunctionList *)
  155.                        malloc(sizeof(DynamicFunctionList));
  156.                 scanner = head;
  157.                 entering = 0;
  158.             }
  159.             else
  160.             {
  161.                 scanner->next = (DynamicFunctionList *)
  162.                         malloc(sizeof(DynamicFunctionList));
  163.                 scanner = scanner->next;
  164.             }
  165.             /*
  166.              * Add one for "_", ie
  167.              * overpaid() will be _overpaid
  168.              */
  169.  
  170.             q = strings + (table_entry->n_un.n_strx - 4) + 1;
  171.  
  172.             strcpy(scanner->funcname, q);
  173.             scanner->func = (func_ptr) (table_entry->n_value +
  174.                             entry_addr);
  175.             scanner->next = NULL;
  176.         }
  177.     }
  178.  
  179.     free(symb_table);
  180.     free(strings);
  181.     return(head);
  182. }
  183.  
  184. func_ptr
  185. dynamic_load(err)
  186.  
  187. char **err;
  188.  
  189. {
  190.     *err = "Dynamic load: Should not be here!";
  191.     return(NULL);
  192. }
  193.  
  194. /* 
  195.  *   ld -N -s -A SYMBOL_TABLE -T ADDR -o TEMPFILE FUNC -libraries
  196.  *
  197.  * We have to take care of dynamic and static linking, as the new code
  198.  * shall be linked with the same type of library.
  199.  */
  200.  
  201. execld(address, tmp_file, filename)
  202.  
  203. char *address, *tmp_file, *filename;
  204.  
  205. {
  206.     /* end of text segment */
  207.     extern char end[];
  208.     int __isnan(double);
  209.     int __open(const char *, int, ...);
  210.  
  211.     char command[256];
  212.     char dyn_libs[10];
  213.     char stat_libs[10];
  214.     int retval;
  215.  
  216.     /* Is __open in the normal text segment? If true, libc was staticely
  217.        linked, otherwise dynamically. */
  218.     if((void *) open < (void *) end) {
  219.         *dyn_libs = 0;
  220.         strcpy(stat_libs, " -lc");
  221.     } else {
  222.         *stat_libs = 0;
  223.         strcpy(dyn_libs, " -lc");
  224.     }
  225.  
  226.     /* Is __isnan in the normal text segment? If true, libc was staticely
  227.        linked, otherwise dynamically. */
  228.     if((void *) open < (void *) end) {
  229.         strcat(stat_libs, " -lm");
  230.     } else {
  231.         strcat(dyn_libs, " -lm");
  232.     }
  233.     
  234.     sprintf(command,"ld -N -s -A %s -T %lx -o %s %s%s",
  235.             pg_pathname, address, tmp_file, filename, dyn_libs);
  236.     if(*stat_libs) {
  237.         strcat(command, " -static");
  238.         strcat(command, stat_libs);
  239.     }
  240.     retval = system(command);
  241.     return(retval);
  242. }
  243.